﻿using System;
using Microsoft.VisualStudio.Modeling.Diagrams;
using Microsoft.VisualStudio.Modeling.Diagrams.GraphObject;

namespace ImTryin.StateMachineLanguage
{
    public partial class StateShape
    {
        public override bool HasConnectionPoints
        {
            get
            {
                return true;
            }
        }

        public override void EnsureConnectionPoints( LinkShape link )
        {
            if ( ConnectionPoints.Count == 0 )
            {
                RectangleD absoluteBoundingBox = AbsoluteBounds;

                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left, absoluteBoundingBox.Top + 0.25 * absoluteBoundingBox.Height ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left, absoluteBoundingBox.Top + 0.50 * absoluteBoundingBox.Height ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left, absoluteBoundingBox.Top + 0.75 * absoluteBoundingBox.Height ) );

                CreateConnectionPoint( new PointD( absoluteBoundingBox.Right, absoluteBoundingBox.Top + 0.25 * absoluteBoundingBox.Height ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Right, absoluteBoundingBox.Top + 0.50 * absoluteBoundingBox.Height ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Right, absoluteBoundingBox.Top + 0.75 * absoluteBoundingBox.Height ) );

                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.250 * absoluteBoundingBox.Width, absoluteBoundingBox.Top ) );
                //CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.375 * absoluteBoundingBox.Width, absoluteBoundingBox.Top ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.500 * absoluteBoundingBox.Width, absoluteBoundingBox.Top ) );
                //CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.625 * absoluteBoundingBox.Width, absoluteBoundingBox.Top ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.750 * absoluteBoundingBox.Width, absoluteBoundingBox.Top ) );

                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.250 * absoluteBoundingBox.Width, absoluteBoundingBox.Bottom ) );
                //CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.375 * absoluteBoundingBox.Width, absoluteBoundingBox.Bottom ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.500 * absoluteBoundingBox.Width, absoluteBoundingBox.Bottom ) );
                //CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.625 * absoluteBoundingBox.Width, absoluteBoundingBox.Bottom ) );
                CreateConnectionPoint( new PointD( absoluteBoundingBox.Left + 0.750 * absoluteBoundingBox.Width, absoluteBoundingBox.Bottom ) );
            }
        }

        private static double CalculateDistanceSquare(PointD point1, PointD point2)
        {
            return Math.Pow( point1.X - point2.X, 2.0 ) + Math.Pow( point1.Y - point2.Y, 2.0 );
        }

        /// <summary>
        /// Calculates compliant AnchorPoint based of the proposedAnchorPoint parameter.
        /// This method completely ignores the co-ordinates of the anchorPoint parameter.
        /// Calculations are done based on the co-ordinates of the proposedAnchorPoint and
        /// the anchorPoint at opposite end of the link corresponding to the anchorPoint parameter.
        /// </summary>
        /// <param name="anchorPoint"></param>
        /// <param name="proposedAnchorPoint"></param>
        /// <param name="routingStyle"></param>
        /// <returns></returns>
        public override PointD GetCompliantAnchorPoint( AnchorPoint anchorPoint, PointD proposedAnchorPoint, VGRoutingStyle routingStyle )
        {
            PointD nearestConnectionPoint = ConnectionPoints[ 0 ].Center;
            double minimalDistanceSquare = CalculateDistanceSquare( proposedAnchorPoint, nearestConnectionPoint );

            foreach ( ConnectionPoint connectionPoint in ConnectionPoints )
            {
                double distanceSquare = CalculateDistanceSquare( proposedAnchorPoint, connectionPoint.Center );
                if ( distanceSquare < minimalDistanceSquare )
                {
                    nearestConnectionPoint = connectionPoint.Center;
                    minimalDistanceSquare = distanceSquare;
                }
            }

            return base.GetCompliantAnchorPoint( anchorPoint, nearestConnectionPoint, routingStyle );
        }
    }
}